﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace linkouqs.Gamekit {

    public enum RaycastDirection {
        Up,
        Down,
        Left,
        Right
    }

    public static class CapsuleCollider2DExtends {

        public static Vector2 GetRaycastDirection(this RaycastDirection direction) {
            switch (direction) {
            case RaycastDirection.Up:
                return Vector2.up;
            case RaycastDirection.Down:
                return Vector2.down;
            case RaycastDirection.Left:
                return Vector2.left;
            case RaycastDirection.Right:
                return Vector2.right;
            }
            return Vector2.zero;
        }

        public static float GetRaycastDistance(this CapsuleCollider2D capsule, float distance = 0.1f) {
            return capsule.size.x * 0.5f + distance;
        }

        public static List<Vector2> GetRaycastPositions(this CapsuleCollider2D capsule,
                                                        RaycastDirection direction, int raycastCount = 3) {
            List<Vector2> results = new List<Vector2>();
            float width = capsule.size.x;
            float halfWidth = width * 0.5f;
            float height = capsule.size.y;
            float halfHeight = height * 0.5f;
            Vector2 center = capsule.transform.position;
            center += capsule.offset;
            Vector2 hOffset = new Vector2(width / (raycastCount - 1), 0);
            Vector2 vOffset = new Vector2(0, height / (raycastCount - 1));
            Vector2 position = center;
            int index = 0;
            switch (direction) {
            case RaycastDirection.Up: {
                    position += new Vector2(-halfWidth, halfHeight - halfWidth);
                    while (index < raycastCount) {
                        results.Add(position + hOffset * index);
                        index++;
                    }
                }
                break;
            case RaycastDirection.Down: {
                    position += new Vector2(-halfWidth, -halfHeight + halfWidth);
                    while (index < raycastCount) {
                        results.Add(position + hOffset * index);
                        index++;
                    }
                }
                break;
            case RaycastDirection.Left:
            case RaycastDirection.Right: {
                    position += new Vector2(0, -halfHeight);
                    while (index < raycastCount) {
                        results.Add(position + vOffset * index);
                        index++;
                    }
                }
                break;
            }
            return results;
        }

        public static List<Collider2D> ComputeColliders(this CapsuleCollider2D capsule, RaycastDirection direction,
                                                        float raycastDistance, LayerMask raycastLayers, int raycastCount = 3) {
            float dist = capsule.GetRaycastDistance(raycastDistance);
            List<Vector2> origins = capsule.GetRaycastPositions(direction, raycastCount);
            List<Collider2D> results = new List<Collider2D>();
            Vector2 dir = direction.GetRaycastDirection();
            foreach (var origin in origins) {
                var hits = Physics2D.RaycastAll(origin, dir, dist, raycastLayers.value);
                foreach (var hit in hits) {
                    if (!hit.collider) {
                        continue;
                    }
                    if (results.Contains(hit.collider)) {
                        continue;
                    }
                    results.Add(hit.collider);
                }
            }
            return results;
        }

        public static void DrawRaycast(this CapsuleCollider2D capsule, float raycastDistance, int raycastCount) {
#if UNITY_EDITOR
            var color = Gizmos.color;
            Gizmos.color = Color.red;
            var dist = capsule.GetRaycastDistance(raycastDistance);

            System.Action<RaycastDirection> draw = (RaycastDirection dir) => {
                List<Vector2> origins = capsule.GetRaycastPositions(dir, raycastCount);
                foreach (var origin in origins) {
                    Gizmos.DrawLine(origin, origin + dir.GetRaycastDirection() * dist);
                }
            };

            draw(RaycastDirection.Up);
            draw(RaycastDirection.Down);
            draw(RaycastDirection.Left);
            draw(RaycastDirection.Right);

            Gizmos.color = color;
#endif
        }

    }

}
